/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package AIModel;

/**
 *
 * @author micheal
 */
import java.util.*;

public class Strategy {	
	
	private Priority weight;
	private Spot point;
	private int Scale;		
	private int level;	
	private boolean competitor;
	
	public Strategy(int s){
		
		weight=new Priority();	
		Scale=s;			
		
	}
	
	public Spot makeStrategy(int ChessBox[][],int turn,int level){
		
		this.level=level;		
		
		point=strategyGenerate(ChessBox,turn,0);
		
		return point;
		
	}
	
	public Spot strategyGenerate(int ChessBox[][],int player,int layer){
		
		ArrayList<int[]> decision=new ArrayList<int[]>();
		ArrayList<int[]> result=new ArrayList<int[]>();		
		
		int standard=0,MinMax=1000000000;
		Spot position=new Spot();
		
		calState(ChessBox,player,decision);
		
		for(int i=0;i<decision.size();i++){
			
			int temp[]=decision.get(i);
			
			if(temp[2]>standard){
				
				result.clear();				
				standard=temp[2];
			}
			if(temp[2]==standard){
				
				int clone[]=new int[3];
				clone[0]=temp[0];
				clone[1]=temp[1];
				clone[2]=temp[2];
				result.add(clone);
			}
		}
		
		if(layer==level){		
		
			long time = Calendar.getInstance().getTimeInMillis();			
			Random generator=new Random();		
			generator.setSeed(time);		
			int shuffle=(int)(generator.nextDouble()*result.size());		
			int spot[]=result.get(shuffle);	
			position.SetX(spot[0]);
			position.SetY(spot[1]);					
			position.setValue(spot[2]);
			return position;
		}else{
			
			for(int i=0;i<result.size();i++){
				int virtual[]=result.get(i);
				ChessBox[virtual[0]][virtual[1]]=player;
				
				Spot perspect=strategyGenerate(ChessBox,-player,layer+1);
				
				if(perspect.getValue()<MinMax){
					position.SetX(virtual[0]);
					position.SetY(virtual[1]);
					position.setValue(virtual[2]);
					MinMax=perspect.getValue();
				}
				
				ChessBox[virtual[0]][virtual[1]]=0;
				
			}
			
			return position;
		}
		
	}
	
	public int calPriority(int x,int y,int ChessBox[][],int player){
		
		
		int p=0,n=0,sum=0;
		boolean sequencep=true,sequencen=true,opponentp=false,opponentn=false;
		
		for(int i=1;i<=4;i++){
			
			if(sequencep&&x-i>=0&&ChessBox[x-i][y]==player){
				p++;
			}else{
				if(sequencep&&((x-i>=0&&ChessBox[x-i][y]==-player)||x-i<0)){
					opponentp=true;
				}
				sequencep=false;
			}
			
			if(sequencen&&x+i<Scale&&ChessBox[x+i][y]==player){
				n++;
			}else{
				if(sequencen&&((x+i<Scale&&ChessBox[x+i][y]==-player)||x+i>=Scale)){
					opponentn=true;
				}
				sequencen=false;
			}
		}		

		if(p+n<4){
			
			if((!opponentp&&opponentn)||(opponentp&&!opponentn)){
				sum+=getWeight(-(p+n+1));
			}else if(!opponentp&&!opponentn){
				
				sum+=getWeight(p+n+1);
			}
		}else{			
			sum+=getWeight(5);
		}
		
		p=0;
		n=0;
		sequencep=true;
		sequencen=true;
		opponentp=false;
		opponentn=false;

		for(int i=1;i<=4;i++){
			
			if(sequencep&&y-i>=0&&ChessBox[x][y-i]==player){
				p++;
			}else{
				if(sequencep&&((y-i>=0&&ChessBox[x][y-i]==-player)||y-i<0)){
					opponentp=true;
				}
				sequencep=false;
			}
			
			if(sequencen&&y+i<Scale&&ChessBox[x][y+i]==player){
				n++;
			}else{
				if(sequencen&&((y+i<Scale&&ChessBox[x][y+i]==-player)||y+i>=Scale)){
					opponentn=true;
				}
				sequencen=false;
			}
		}

		if(p+n<4){
			
			if((!opponentp&&opponentn)||(opponentp&&!opponentn)){
				sum+=getWeight(-(p+n+1));
			}else if(!opponentp&&!opponentn){
				
				sum+=getWeight(p+n+1);
			}
		}else{			
			sum+=getWeight(5);
		}
		
		p=0;
		n=0;
		sequencep=true;
		sequencen=true;
		opponentp=false;
		opponentn=false;	

		for(int i=1;i<=4;i++){
			
			if(sequencep&&x-i>=0&&y-i>=0&&ChessBox[x-i][y-i]==player){
				p++;
			}else{
				if(sequencep&&((x-i>=0&&y-i>=0&&ChessBox[x-i][y-i]==-player)||x-i<0||y-i<0)){
					opponentp=true;
				}
				sequencep=false;
			}
			
			if(sequencen&&x+i<Scale&&y+i<Scale&&ChessBox[x+i][y+i]==player){
				n++;
			}else{
				if(sequencen&&((x+i<Scale&&y+i<Scale&&ChessBox[x+i][y+i]==-player)||x+i>=Scale||y+i>=Scale)){
					opponentn=true;
				}
				sequencen=false;
			}
		}	
		
		if(p+n<4){
			
			if((!opponentp&&opponentn)||(opponentp&&!opponentn)){
				sum+=getWeight(-(p+n+1));
			}else if(!opponentp&&!opponentn){
				
				sum+=getWeight(p+n+1);
			}
		}else{			
			sum+=getWeight(5);
		}
		
		p=0;
		n=0;
		sequencep=true;
		sequencen=true;
		opponentp=false;
		opponentn=false;	

		for(int i=1;i<=4;i++){
			
			if(sequencep&&x-i>=0&&y+i<Scale&&ChessBox[x-i][y+i]==player){
				p++;
			}else{
				if(sequencep&&((x-i>=0&&y+i<Scale&&ChessBox[x-i][y+i]==-player)||x-i<0||y+i>=Scale)){
					opponentp=true;
				}
				sequencep=false;
			}
			
			if(sequencen&&x+i<Scale&&y-i>=0&&ChessBox[x+i][y-i]==player){
				n++;
			}else{
				if(sequencen&&((x+i<Scale&&y-i>=0&&ChessBox[x+i][y-i]==-player)||x+i>=Scale||y-i<0)){
					opponentn=true;
				}
				sequencen=false;
			}
		}		

		if(p+n<4){			
						
			if((!opponentp&&opponentn)||(opponentp&&!opponentn)){				
				sum+=getWeight(-(p+n+1));
			}else if(!opponentp&&!opponentn){
				
				sum+=getWeight(p+n+1);
			}
		}else{			
			sum+=getWeight(5);
		}		
		
		
		return sum;		
		
		
	}
	
	public int getWeight(int pri){
		
		if(competitor){
			pri+=10;
		}

		switch(pri){
		
		case -1:
			return weight.getPriority("d1");
			
		case -2:
			return weight.getPriority("d2");		
			
		case -3:
			return weight.getPriority("d3");	
			
		case -4:
			return weight.getPriority("d4");		
			
		case 2:
			return weight.getPriority("a2");
			
		case 3:
			return weight.getPriority("a3");		
			
		case 4:
			return weight.getPriority("a4");
		
		case 5:
			return weight.getPriority("a5");			
			
		case 9:
			return weight.getPriority("d1")-2;
			
		case 8:
			return weight.getPriority("d2")-30;	
			
		case 7:
			return weight.getPriority("d3")-150;
			
		case 6:
			return weight.getPriority("d4")-800;	
			
		case 12:
			return weight.getPriority("a2")-8;
			
		case 13:
			return weight.getPriority("a3")-3000;	
			
		case 14:
			return weight.getPriority("a4")-10000;
			
		case 15:
			return weight.getPriority("a5")-2000000;
		
		default:
			return 0;
		}	
		
	}
	
	public int calState(int ChessBox[][],int player,ArrayList<int[]> decision){
		
		int total=0,temp=0,rival;
		
		for(int i=0;i<Scale;i++){
			
			for(int j=0;j<Scale;j++){
				temp=0;
				competitor=false;
				
				if(ChessBox[i][j]==0){					
					temp=calPriority(i,j,ChessBox,player);	
					competitor=true;
					rival=calPriority(i,j,ChessBox,-player);
					
					//if(rival>6000){
						//rival-=2000;
					//}
					temp+=rival;
				}				
				
				if(temp>0){
					
					int locate[]=new int[3];
					
					locate[0]=i;
					locate[1]=j;
					locate[2]=temp;
					
					decision.add(locate);					
					
				}
				total+=temp;				
				
			}
		}
		
		return total;
		
	}	
	
	public int checkWin(int ChessBox[][]){
		
		for(int i=0;i<Scale;i++){
			
			for(int j=0;j<Scale;j++){
				
				if(ChessBox[i][j]!=0){
					
					if(lineCheck(i,j,ChessBox)){
						
						return ChessBox[i][j];
					}
				}
			}
		}
		
		return 0;
		
	}
	
	public boolean lineCheck(int x, int y, int ChessBox[][]){		
		
		
		int p1=0,n1=0,p2=0,n2=0,p3=0,n3=0,p4=0,n4=0;
		
		boolean sequencep1=true,sequencen1=true,sequencep2=true,sequencen2=true,sequencep3=true,sequencen3=true,sequencep4=true,sequencen4=true;
		
		for(int i=1;i<=4;i++){			
			
			if(sequencep1&&x-i>=0&&ChessBox[x-i][y]==ChessBox[x][y]){				
				p1++;	
				
			}else{
				sequencep1=false;
			}		
			
			if(sequencen1&&x+i<Scale&&ChessBox[x+i][y]==ChessBox[x][y]){				
				n1++;				
			}else{
				sequencen1=false;
			}
			
			if(sequencep2&&y-i>=0&&ChessBox[x][y-i]==ChessBox[x][y]){				
				p2++;				
			}else{
				sequencep2=false;
			}		
			
			if(sequencen2&&y+i<Scale&&ChessBox[x][y+i]==ChessBox[x][y]){				
				n2++;				
			}else{
				sequencen2=false;
			}
			
			if(sequencep3&&x-i>=0&&y-i>=0&&ChessBox[x-i][y-i]==ChessBox[x][y]){				
				p3++;				
			}else{
				sequencep3=false;
			}		
			
			if(sequencen3&&x+i<Scale&&y+i<Scale&&ChessBox[x+i][y+i]==ChessBox[x][y]){				
				n3++;				
			}else{
				sequencen3=false;
			}	
			
			if(sequencep4&&x-i>=0&&y+i<Scale&&ChessBox[x-i][y+i]==ChessBox[x][y]){				
				p4++;				
			}else{
				sequencep4=false;
			}		
			
			if(sequencen4&&x+i<Scale&&y-i>=0&&ChessBox[x+i][y-i]==ChessBox[x][y]){				
				n4++;				
			}else{
				sequencen4=false;
			}
			
		}		
		
		if(p1+n1>=4||p2+n2>=4||p3+n3>=4||p4+n4>=4){			
			
			return true;
		}else{
			
			return false;
		}
		
	}

}
